package main

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

const (
	workerIdBits   uint8 = 10
	sequenceBits   uint8 = 12
	maxWorkerId    int64 = -1 ^ (-1 << workerIdBits)
	maxSequence    int64 = -1 ^ (-1 << sequenceBits)
	timestampShift       = workerIdBits + sequenceBits
	sequenceShift        = sequenceBits
)

// 起始时间戳 (毫秒数显示)
var Epoch int64 = 1583723446402 // timestamp 2020-03-09 11:10:46
type UUID int64

type Node struct {
	mu        sync.Mutex
	timestamp int64
	workerId  int64
	sequence      int64
}

// 生成、返回唯一 snowflake ID
func (n *Node) GenerateUUID() UUID {

	n.mu.Lock()
	defer n.mu.Unlock()

	// 获取当前时间的时间戳 (毫秒数显示)
	currentTimestamp := time.Now().UnixNano() / 1e6

	if n.timestamp == currentTimestamp {
		// sequence 步进 1
		n.sequence++

		// 当前 sequence 用完
		if n.sequence > maxSequence {
			// 等待本毫秒结束
			for currentTimestamp <= n.timestamp {
				currentTimestamp = time.Now().UnixNano() / 1e6
			}
		}

	} else {
		// 本毫秒内 sequence 用完
		n.sequence = 0
	}

	n.timestamp = currentTimestamp

	return UUID((currentTimestamp - Epoch) << timestampShift | (n.workerId << sequenceShift) | (n.sequence))
}

func NewNode(workerId int64) (*Node, error) {

	if workerId < 0 || workerId > maxWorkerId {
		return nil, errors.New("Node number must be between 0 and 1023")
	}

	return &Node{
		timestamp: 0,
		workerId:  workerId,
		sequence:      0,
	}, nil
}

func main() {
	// 测试

	// 生成节点实例
	node, err := NewNode(1)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(node.GenerateUUID())


}
